home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / PropertyDescriptor.java < prev    next >
Text File  |  1998-09-22  |  9KB  |  266 lines

  1. /*
  2.  * @(#)PropertyDescriptor.java    1.37 98/07/01
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.beans;
  16.  
  17. import java.lang.reflect.*;
  18.  
  19. /**
  20.  * A PropertyDescriptor describes one property that a Java Bean
  21.  * exports via a pair of accessor methods.
  22.  */
  23.  
  24. public class PropertyDescriptor extends FeatureDescriptor {
  25.  
  26.     /**
  27.      * Constructs a PropertyDescriptor for a property that follows
  28.      * the standard Java convention by having getFoo and setFoo 
  29.      * accessor methods.  Thus if the argument name is "fred", it will
  30.      * assume that the reader method is "getFred" and the writer method 
  31.      * is "setFred".  Note that the property name should start with a lower
  32.      * case character, which will be capitalized in the method names.
  33.      *
  34.      * @param propertyName The programmatic name of the property.
  35.      * @param beanClass The Class object for the target bean.  For
  36.      *        example sun.beans.OurButton.class.
  37.      * @exception IntrospectionException if an exception occurs during
  38.      *              introspection.
  39.      */
  40.     public PropertyDescriptor(String propertyName, Class beanClass)
  41.         throws IntrospectionException {
  42.     setName(propertyName);
  43.     String base = capitalize(propertyName);
  44.     writeMethod = Introspector.findMethod(beanClass, "set" + base, 1);
  45.     // If it's a boolean property check for an "isFoo" first.
  46.     if (writeMethod.getParameterTypes()[0] == Boolean.TYPE) {
  47.         try {
  48.         readMethod = Introspector.findMethod(beanClass, "is" + base, 0);
  49.         } catch (Exception ex) {
  50.         }
  51.     }
  52.     if (readMethod == null) {
  53.         readMethod = Introspector.findMethod(beanClass, "get" + base, 0);
  54.     }
  55.     findPropertyType();
  56.     }
  57.  
  58.     /**
  59.      * This constructor takes the name of a simple property, and method
  60.      * names for reading and writing the property.
  61.      *
  62.      * @param propertyName The programmatic name of the property.
  63.      * @param beanClass The Class object for the target bean.  For
  64.      *        example sun.beans.OurButton.class.
  65.      * @param getterName The name of the method used for reading the property
  66.      *         value.  May be null if the property is write-only.
  67.      * @param setterName The name of the method used for writing the property
  68.      *         value.  May be null if the property is read-only.
  69.      * @exception IntrospectionException if an exception occurs during
  70.      *              introspection.
  71.      */
  72.     public PropertyDescriptor(String propertyName, Class beanClass,
  73.         String getterName, String setterName)
  74.         throws IntrospectionException {
  75.     setName(propertyName);
  76.     readMethod = Introspector.findMethod(beanClass, getterName, 0);
  77.     writeMethod = Introspector.findMethod(beanClass, setterName, 1);
  78.     findPropertyType();
  79.     }
  80.  
  81.     /**
  82.      * This constructor takes the name of a simple property, and Method
  83.      * objects for reading and writing the property.
  84.      *
  85.      * @param propertyName The programmatic name of the property.
  86.      * @param getter The method used for reading the property value.
  87.      *        May be null if the property is write-only.
  88.      * @param setter The method used for writing the property value.  
  89.      *        May be null if the property is read-only.
  90.      * @exception IntrospectionException if an exception occurs during
  91.      *              introspection.
  92.      */
  93.     public PropertyDescriptor(String propertyName, Method getter, Method setter)
  94.         throws IntrospectionException {
  95.     setName(propertyName);
  96.     readMethod = getter;
  97.     writeMethod = setter;
  98.     findPropertyType(); 
  99.     }
  100.     
  101.     /**
  102.      * @return The Java type info for the property.  Note that
  103.      * the "Class" object may describe a built-in Java type such as "int".
  104.      * The result may be "null" if this is an indexed property that
  105.      * does not support non-indexed access.
  106.      * <p>
  107.      * This is the type that will be returned by the ReadMethod.
  108.      */
  109.     public Class getPropertyType() {
  110.     return propertyType;
  111.     }
  112.  
  113.     /**
  114.      * @return The method that should be used to read the property value.
  115.      * May return null if the property can't be read.
  116.      */
  117.     public Method getReadMethod() {
  118.     return readMethod;
  119.     }
  120.  
  121.     /**
  122.      * @return The method that should be used to write the property value.
  123.      * May return null if the property can't be written.
  124.      */
  125.     public Method getWriteMethod() {
  126.     return (writeMethod);
  127.     }
  128.  
  129.     /**
  130.      * Updates to "bound" properties will cause a "PropertyChange" event to
  131.      * get fired when the property is changed.
  132.      *
  133.      * @return True if this is a bound property.
  134.      */
  135.     public boolean isBound() {
  136.     return (bound);
  137.     }
  138.  
  139.     /**
  140.      * Updates to "bound" properties will cause a "PropertyChange" event to 
  141.      * get fired when the property is changed.
  142.      *
  143.      * @param bound True if this is a bound property.
  144.      */
  145.     public void setBound(boolean bound) {
  146.     this.bound = bound;
  147.     }
  148.  
  149.     /**
  150.      * Attempted updates to "Constrained" properties will cause a "VetoableChange"
  151.      * event to get fired when the property is changed.
  152.      *
  153.      * @return True if this is a constrained property.
  154.      */
  155.     public boolean isConstrained() {
  156.     return (constrained);
  157.     }
  158.  
  159.     /**
  160.      * Attempted updates to "Constrained" properties will cause a "VetoableChange"
  161.      * event to get fired when the property is changed.
  162.      *
  163.      * @param constrained True if this is a constrained property.
  164.      */
  165.     public void setConstrained(boolean constrained) {
  166.     this.constrained = constrained;
  167.     }
  168.  
  169.  
  170.     /**
  171.      * Normally PropertyEditors will be found using the PropertyEditorManager.
  172.      * However if for some reason you want to associate a particular
  173.      * PropertyEditor with a given property, then you can do it with
  174.      * this method.
  175.      * @param propertyEditorClass  The Class for the desired PropertyEditor.
  176.      */
  177.     public void setPropertyEditorClass(Class propertyEditorClass) {
  178.     this.propertyEditorClass = propertyEditorClass;
  179.     }
  180.  
  181.     /**
  182.      * @return Any explicit PropertyEditor Class that has been registered
  183.      *        for this property.  Normally this will return "null",
  184.      *        indicating that no special editor has been registered,
  185.      *        so the PropertyEditorManager should be used to locate
  186.      *        a suitable PropertyEditor.
  187.      */
  188.     public Class getPropertyEditorClass() {
  189.     return propertyEditorClass;
  190.     }
  191.  
  192.     /*
  193.      * Package-private constructor.
  194.      * Merge two property descriptors.  Where they conflict, give the
  195.      * second argument (y) priority over the first argumnnt (x).
  196.      * @param x  The first (lower priority) PropertyDescriptor
  197.      * @param y  The second (higher priority) PropertyDescriptor
  198.      */
  199.  
  200.     PropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
  201.     super(x,y);
  202.     readMethod = x.readMethod;
  203.     propertyType = x.propertyType;
  204.     if (y.readMethod != null) {
  205.         readMethod = y.readMethod;
  206.     }
  207.     writeMethod = x.writeMethod;
  208.     if (y.writeMethod != null) {
  209.         writeMethod = y.writeMethod;
  210.     }
  211.     propertyEditorClass = x.propertyEditorClass;
  212.     if (y.propertyEditorClass != null) {
  213.         propertyEditorClass = y.propertyEditorClass;
  214.     }
  215.     bound = x.bound | y.bound;
  216.     constrained = x.constrained | y.constrained;
  217.     try {
  218.         findPropertyType();
  219.     } catch (IntrospectionException ex) {
  220.         // Given we're merging two valid PDs, this "should never happen".
  221.         throw new Error("PropertyDescriptor: internal error while merging PDs");
  222.     }
  223.     }
  224.  
  225.     private void findPropertyType() throws IntrospectionException {
  226.     try {
  227.         propertyType = null;
  228.         if (readMethod != null) {
  229.         if (readMethod.getParameterTypes().length != 0) {
  230.             throw new IntrospectionException("bad read method arg count");
  231.         }
  232.         propertyType = readMethod.getReturnType();
  233.         if (propertyType == Void.TYPE) {
  234.             throw new IntrospectionException("read method " + 
  235.                     readMethod.getName() + " returns void");
  236.         }
  237.         }
  238.         if (writeMethod != null) {
  239.         Class params[] = writeMethod.getParameterTypes();
  240.         if (params.length != 1) {
  241.             throw new IntrospectionException("bad write method arg count");
  242.         }
  243.         if (propertyType != null && propertyType != params[0]) {
  244.             throw new IntrospectionException("type mismatch between read and write methods");
  245.         }
  246.         propertyType = params[0];
  247.         }
  248.     } catch (IntrospectionException ex) {
  249.         throw ex;
  250.     }
  251.     }
  252.  
  253.     private String capitalize(String s) {
  254.     char chars[] = s.toCharArray();
  255.     chars[0] = Character.toUpperCase(chars[0]);
  256.     return new String(chars);
  257.     }
  258.  
  259.     private Class propertyType;
  260.     private Method readMethod;
  261.     private Method writeMethod;
  262.     private boolean bound;
  263.     private boolean constrained;
  264.     private Class propertyEditorClass;
  265. }
  266.